package arch.chameleon.module.web;

import static arch.chameleon.support.constants.WebConstants.REQ_BODY;
import static arch.chameleon.support.constants.WebConstants.REQ_HEADER_X_REQUESTED_WITH;
import static arch.chameleon.support.constants.WebConstants.REQ_TYPE_XHR;
import static arch.chameleon.support.constants.WebConstants.RSP_BODY;
import static arch.chameleon.support.constants.WebConstants.RSP_HEAD;
import static arch.chameleon.support.constants.WebConstants.RSP_MSG;
import static arch.chameleon.support.constants.WebConstants.RSP_STATUS;
import static arch.chameleon.support.constants.WebConstants.RSP_STATUS_FAILURE;
import static arch.chameleon.support.constants.WebConstants.RSP_STATUS_SESSION_EXPIRE;
import static arch.chameleon.support.constants.WebConstants.RSP_STATUS_SUCCESS;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;
import org.springframework.web.util.WebUtils;

import arch.chameleon.module.web.bind.ServletRequestBodyDataBinder;

/**
 * 用户定制控制器
 * 
 * @author George
 * 
 */
public abstract class AbstractUserController extends MultiActionController {

	/**
	 * 创建ModelAndView实例
	 * 
	 * @return
	 */
	protected ModelAndView createMAV() {
		return new ModelAndView();
	}
	
	
	/**
	 * 创建ModelAndView实例
	 *
	 * @param viewName 视图名称
	 * @return
	 */
	protected ModelAndView createMAV(String viewName) {
		return new ModelAndView(viewName);
	}
	
	
	/**
	 * 返回成功视图
	 * @param model 参数模型
	 * @param async 是否异步
	 * @return
	 */
	protected ModelAndView rtnSuccessView(Map<String, Object> model, boolean async){
		if(async){
			if(model == null){
				model = new HashMap<String, Object>();
			}
			Map<String, String> mpRspHead = new HashMap<String, String>();
			mpRspHead.put(RSP_STATUS, RSP_STATUS_SUCCESS);			
			return new ModelAndView()
				.addObject(RSP_HEAD, mpRspHead)
				.addObject(RSP_BODY, model);
		}else{
			return new ModelAndView().addAllObjects(model);
		}
	}
	
	/**
	 * 返回失败视图
	 * @param model 参数模型
	 * @param async 是否异步
	 * @param t 异常
	 * @return
	 */
	protected ModelAndView rtnFailureView(Map<String, Object> model, boolean async, Throwable t){
		if(async){
			if(model == null){
				model = new HashMap<String, Object>();
			}
			Map<String, String> mpRspHead = new HashMap<String, String>();
			mpRspHead.put(RSP_STATUS, RSP_STATUS_FAILURE);	
			mpRspHead.put(RSP_MSG, t == null ? "" : t.getMessage());
			return new ModelAndView()
				.addObject(RSP_HEAD, mpRspHead)
				.addObject(RSP_BODY, model);
		}else{
			return new ModelAndView().addAllObjects(model);
		}
	}
	
	/**
	 * 异步返回Session超时视图
	 * @param sessionExpireMessage session超时信息
	 * @param model 参数模型
	 * @return
	 */
	protected ModelAndView rtnSessionExpiredView(String sessionExpireMessage, Map<String, Object> model){

		if(model == null){
			model = new HashMap<String, Object>();
		}
		Map<String, String> mpRspHead = new HashMap<String, String>();
		mpRspHead.put(RSP_STATUS, RSP_STATUS_SESSION_EXPIRE);	
		mpRspHead.put(RSP_MSG, sessionExpireMessage);
		return new ModelAndView()
				.addObject(RSP_HEAD, mpRspHead)
				.addObject(RSP_BODY, model);
	
	}

	/**
	 * 通过请求参数绑定Model
	 * 
	 * @param request
	 * @param clazz
	 * @return
	 * @throws Exception
	 */
	protected <T> T bindModel(HttpServletRequest request, Class<T> clazz)
			throws Exception {
		T object = (T) newCommandObject(clazz);
		bind(request, object);
		return object;
	}

	/**
	 * 从请求中获取Integer类型参数
	 * @param request
	 * @param name
	 * @return
	 */
	protected Integer findIntegerParameterValue(HttpServletRequest request,
			String name) {
		return Integer.parseInt(WebUtils.findParameterValue(request, name));
	}
	
	/**
	 * 从REQ_BODY的属性中获取Integer类型参数
	 * @param request
	 * @param name
	 * @return
	 */
	protected Integer findIntegerBodyValue(HttpServletRequest request,
			String name) {
		return Integer.parseInt((String)findRequestBody(request).get(name));
	}

	/**
	 * 从请求中获取Long类型参数
	 * @param request
	 * @param name
	 * @return
	 */
	protected Long findLongParameterValue(HttpServletRequest request,
			String name) {
		return Long.parseLong(String.valueOf(request.getAttribute(name)));
	}
	
	/**
	 * 从REQ_BODY的属性中获取Long类型参数
	 * @param request
	 * @param name
	 * @return
	 */
	protected Long findLongBodyValue(HttpServletRequest request,
			String name) {
		return Long.parseLong((String)findRequestBody(request).get(name));
	}

	/**
	 * 从请求中获取String类型参数
	 * @param request
	 * @param name
	 * @return
	 */
	protected String findStringParameterValue(HttpServletRequest request,
			String name) {
		return WebUtils.findParameterValue(request, name);
	}
	
	/**
	 * 从REQ_BODY的属性中获取String类型参数
	 * @param request
	 * @param name
	 * @return
	 */
	protected String findStringBodyValue(HttpServletRequest request,
			String name) {
		return (String)findRequestBody(request).get(name);
	}

	/**
	 * 从请求中获取Boolean类型参数
	 * @param request
	 * @param name
	 * @return
	 */
	protected Boolean findBooleanParameterValue(HttpServletRequest request,
			String name) {
		return Boolean.parseBoolean(WebUtils.findParameterValue(request, name));
	}
	
	/**
	 * 从REQ_BODY的属性中获取Boolean类型参数
	 * @param request
	 * @param name
	 * @return
	 */
	protected Boolean findBooleanBodyValue(HttpServletRequest request,
			String name) {
		return Boolean.parseBoolean((String)findRequestBody(request).get(name));
	}

	/**
	 * 从请求中获取Date类型参数
	 * @param request
	 * @param name
	 * @param datePattern 日期匹配模式
	 * @return
	 */
	protected Date findDateParameterValue(HttpServletRequest request,
			String name, String datePattern) throws ParseException {
		DateFormat objFmt = new SimpleDateFormat(datePattern);
		return objFmt.parse(WebUtils.findParameterValue(request, name));
	}
	
	/**
	 * 从REQ_BODY的属性中获取Date类型参数
	 * @param request
	 * @param name
	 * @param datePattern 日期匹配模式
	 * @return
	 */
	protected Date findDateBodyValue(HttpServletRequest request,
			String name, String datePattern) throws ParseException {
		DateFormat objFmt = new SimpleDateFormat(datePattern);
		return objFmt.parse((String)findRequestBody(request).get(name));
	}
	
	
	/**
	 * 从请求属性中获取REQ_BODY
	 * @param request
	 * @return
	 */
	protected Map<String, Object> findRequestBody(HttpServletRequest request){
		return (Map)request.getAttribute(REQ_BODY);
	}


	@Override
	protected ServletRequestDataBinder createBinder(HttpServletRequest request, Object command) throws Exception {
		if((request.getHeader(REQ_HEADER_X_REQUESTED_WITH) != null 
					 && request.getHeader(REQ_HEADER_X_REQUESTED_WITH).indexOf(REQ_TYPE_XHR) > -1)){//异步处理request Body
			log.debug("using request body data binder");
			//使用request body data binder
			ServletRequestBodyDataBinder binder = new ServletRequestBodyDataBinder(command, getCommandName(command));
			initBinder(request, binder);
			return binder;
		}else{
			log.debug("using default data binder");
			return super.createBinder(request, command);
		}
		
	}

	protected transient Logger log = LoggerFactory.getLogger(this.getClass());
}
